#pragma once
#include "CXcpObjectBase.h"
#include "NoBaseClass.h"
#include "CXcpObjectThreadSafeAddRefPolicy.h"
#include "IInvalidateDecodedImageCacheCallback.h"
#include "ImageDecodeRequest.h"


class ImageCacheDecodeCallback;
class ImageTaskDispatcher;
class CBitmapImage;
class DecodedImageCache;
class ImageCacheDownloadCallback;


class ImageCache :
	public CXcpObjectBase<NoBaseClass,CXcpObjectThreadSafeAddRefPolicy>,
	public IInvalidateDecodedImageCacheCallback
{

public: 
	static HRESULT Create(CXString * pUri, struct IPALUri * pAbsoluteUri, CCoreServices * pCore, ImageTaskDispatcher * pDispatcher, struct IPALAsyncImageFactory * pImageFactory, struct IInvalidateImageCacheCallback * pInvalidateCallback, ImageCache * * ppImageCache);
	HRESULT GetImage(XUINT32 getEncodedImageOnly, const struct PALImageDecodeParams & params, struct IImageAvailableCallback * pCallback, struct IPALAbortableOperation * * ppGetOperation);
	CXString * GetUri();
	struct IPALUri * GetAbsoluteUri();
	HRESULT GotDownloadResponse(struct IPALDownloadResponse * pResponse, HRESULT status);
	HRESULT GotDownloadProgressUpdate(XUINT64 size, XUINT64 totalSize);
	HRESULT OnDecode(ImageCacheDecodeCallback * pCallback, struct IPALImageDecodeResponse * pResponse);
	HRESULT HandleDecodeResponse(struct IPALImageDecodeResponse * pResponse);
	HRESULT ProcessDecodeRequests();
	XUINT32 InUse();
	HRESULT GotFinalUrl(CXString * pUrl, XUINT32 redirected);
	HRESULT AttachBitmapImage(CBitmapImage * pBitmapImage);
	HRESULT DetachBitmapImage(CBitmapImage * pBitmapImage);
	void OnProviderReleased();

private: 
	ImageCache();
	virtual ~ImageCache();
	HRESULT Initialize(CXString * pUri, struct IPALUri * pAbsoluteUri, CCoreServices * pCore, ImageTaskDispatcher * pDispatcher, struct IPALAsyncImageFactory * pImageFactory, struct IInvalidateImageCacheCallback * pInvalidateCallback);
	HRESULT Download();
	HRESULT AddDecodeRequest(const struct PALImageDecodeParams & params, struct IImageAvailableCallback * pCallback, ImageDecodeRequest * * ppDecodeRequest);
	HRESULT TriggerProcessDecodeRequests();
	HRESULT BeginDecode(ImageDecodeRequest * pDecodeRequest);
	virtual HRESULT OnCacheInvalidated(DecodedImageCache * pCache);
	HRESULT TriggerDownloadProgressUpdate();
	HRESULT RaiseDownloadProgress();
	CCoreServices * m_pCore;
	ImageTaskDispatcher * m_pDispatcher;
	struct IPALAsyncImageFactory * m_pImageFactory;
	CXString * m_pUri;
	struct IPALUri * m_pAbsoluteUri;
	enum ImageCacheState::Value m_State;
	ImageCacheDownloadCallback * m_pDownloadCallback;
	struct IPALAbortableOperation * m_pDownloadOperation;
	HRESULT m_downloadError;
	struct IPALImageSource * m_pEncodedImage;
	xvector<CBitmapImage *> m_bitmapImagesUsingCacheNoRef;
	xvector<xref_ptr<ImageDecodeRequest> > m_decodeRequests;
	xvector<xref_ptr<ImageDecodeRequest> > m_decodingRequests;
	xvector<xref_ptr<DecodedImageCache> > m_decodedImages;
	struct IInvalidateImageCacheCallback * m_pInvalidatedCallback;
	XFLOAT m_downloadProgress;
	struct IPALCriticalSection * m_pDecodedImagesLock;
	struct  
	{
		XUINT32 m_hasProcessDecodeRequestsTask:1;
		XUINT32 m_hasDownloadProgressTask:1;
		XUINT32 m_protectedContent:1;
		XUINT32 m_isProviderReleased:1;
	};

};
